package com.tian.service.impl;

import com.tian.constant.RabbitMQConstant;
import com.tian.entity.RetryMessage;
import com.tian.enums.MessageRetryType;
import com.tian.factory.ApplicationContextFactory;
import com.tian.mapper.RetryMessageMapper;
import com.tian.service.UserGetCouponAdditionalFailedService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;

/**
 * {@code @description:} 用户领取优惠券失败重试服务实现类
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-09-22 17:13
 * {@code @version:} 1.0
 */
@Slf4j
@Service
public class UserGetCouponAdditionalFailedServiceImpl implements UserGetCouponAdditionalFailedService {
    @Resource
    private RetryMessageMapper retryMessageMapper;

    @Override
    public void doRetrySendMessage() {
        List<RetryMessage> retryMessages = retryMessageMapper.selectRetryMessage(MessageRetryType.USER_GET_COUPON_ADDITIONAL.getCode(), 0);
        for (RetryMessage retryMessage : retryMessages) {
            // 消息重发次数大于5次，告警邮件
            if (retryMessage.getRetriedTimes() >= 5) {
                // TODO: 2024-09-22 发送告警邮件
                continue;
            }

            retrySend(retryMessage.getContent(),
                    RabbitMQConstant.USER_GET_COUPON_ADDITIONAL_EXCHANGE, RabbitMQConstant.USER_GET_COUPON_ADDITIONAL_ROUTING_KEY, retryMessage);
        }
    }

    public void retrySend(String content, String mqExchange, String mqRoutingKey, RetryMessage retryMessage) {

        RabbitTemplate rabbitTemplate = ApplicationContextFactory.getBean(RabbitTemplate.class);

        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());

        rabbitTemplate.convertAndSend(mqExchange
                , mqRoutingKey, content, message1 -> {
                    message1.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                    return message1;
                }, correlationId);

        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("户领取优惠券失败重试投递成功 关联数据：{},投递成功,确认情况：{}", correlationData, ack);
                //消息重发成功，更新状态
                retryMessage.setStatus(1);
                retryMessageMapper.updateByPrimaryKey(retryMessage);
            } else {
                //重发次数加1
                retryMessage.setRetriedTimes(retryMessage.getRetriedTimes() + 1);
                retryMessageMapper.updateByPrimaryKey(retryMessage);
                log.info("户领取优惠券失败重试投递失败 关联数据：{},投递失败,确认情况：{}，原因：{}", correlationData, ack, cause);
            }
        });

        rabbitTemplate.setReturnCallback((msg, replyCode, replyText, exchange, routingKey) -> {
            log.info("户领取优惠券失败重试投递 ReturnsCallback 消息：{},回应码：{},回应信息：{},交换机：{},路由键：{}"
                    , msg, replyCode
                    , replyText, exchange
                    , routingKey);
        });
    }
}
